package models

import (
	"GoAdmin/utils"
	"errors"
	"fmt"
	"github.com/go-xorm/xorm"
	"github.com/spf13/cast"
	"log"
	"time"
	"xorm.io/builder"
)

type LearnRecord struct {
	Id                int       `xorm:"not null pk autoincr comment('自增主键') INT(11)"`
	SchoolId          int       `xorm:"not null comment('驾校id外键关联dts_school表中的id') index INT(11)"`
	StudentId         int       `xorm:"not null comment('学员id外键关联dts_student表中的id') index INT(11)"`
	CoachId           int       `xorm:"not null comment('教练员id外键关联dts_coach表中的id') index INT(11)"`
	CarId             int       `xorm:"not null comment('教练车id外键关联dts_car表中的id') index INT(11)"`
	TerminalId        int       `xorm:"not null comment('计时终端设备id外键关联dts_terminal中的id') index INT(11)"`
	Type              string    `xorm:"default '0' comment('该段学时类型标识，1：实车教学,2:课堂教学,3:模拟器教学,4:远程教学') ENUM('0','1','2','3','4','5')"`
	Subject           string    `xorm:"not null default '1' comment('科目一二三四') ENUM('1','2','3','4')"`
	StartTime         time.Time `xorm:"not null comment('学时开始时间') index DATETIME"`
	EndTime           time.Time `xorm:"not null comment('学时结束时间') index DATETIME"`
	LastingMinute     int       `xorm:"comment('此次学车持续时间单位分钟') SMALLINT(5)"`
	ApprovalStatus    string    `xorm:"default '0' comment('本次学时提交运管审核状态，0:待审核，1:合格，2:不合格') ENUM('0','1','2')"`
	RecordStatus      string    `xorm:"not null default '0' comment('备案状态 0:未备案 1:已备案') ENUM('0','1')"`
	Mileage           float32   `xorm:"comment('里程') FLOAT(12,3)"`
	MaxVelocity       float32   `xorm:"comment('最大速度 km/h') FLOAT(12,3)"`
	Reason            string    `xorm:"comment('未通过审核的原因  ') TEXT"`
	LearnrecordNumber string    `xorm:"comment('课堂id') index CHAR(26)"`
	Coachloginid      int       `xorm:"INT(11)"`
	Course            string    `xorm:"comment('课程编码（10位属性码）') VARCHAR(10)"`
	Sn                string    `xorm:"comment('学时编号') VARCHAR(21)"`
	Lastsn            int       `xorm:"default 0 INT(11)"`
	Mongoid           string    `xorm:"default '' index VARCHAR(24)"`
	Ispost            string    `xorm:"default '0' comment('是否已上报公安系统  0 未上报  1 已上报') ENUM('0','1')"`
	Isreport          string    `xorm:"default '0' comment('0未进行上报，1已经上报') ENUM('0','1')"`
	Iscongye          string    `xorm:"default '0' comment('0否，1是') ENUM('0','1')"`
	Iskaohe           string    `xorm:"default '0' comment('0否，1是') ENUM('0','1')"`
	ReportNum         string    `xorm:"default '' comment('上报备案编号') VARCHAR(255)"`
	Ischeck           int       `xorm:"default 0 comment('0未过滤1已过滤') index SMALLINT(6)"`
	RecordTime        time.Time `xorm:"not null default 'CURRENT_TIMESTAMP' comment('备案时间') DATETIME"`
	Xsnumber          string    `xorm:"-"`
	AverageSpeed      float32   `xorm:"-"`
	Isneed            string    `xorm:"-"`
}

type UnRecordList struct {
	Id              int     `json:"id"`
	NameShort       string  `json:"name_short"`
	Name            string  `json:"name"`
	CoachName       string  `json:"coach_name"`
	CarNumber       string  `json:"car_number"`
	Phone           string  `json:"phone"`
	IdNumber        string  `json:"id_number"`
	TrainingCarType string  `json:"training_car_type"`
	OperationStatus string  `json:"operation_status"`
	Subject         string  `json:"subject"`
	StartTime       string  `json:"start_time"`
	EndTime         string  `json:"end_time"`
	LastingMinute   int     `json:"lasting_minute"`
	Mileage         float32 `json:"mileage"`
	Reason          string  `json:"reason"`
	PlateNumber     string  `json:"plate_number"`
	ApprovalStatus  string  `json:"approval_status"`
	RecordStatus    string  `json:"record_status"`
	Course          string  `json:"course"`
	Title           string  `json:"title"`
}

type RecordSurvey struct {
	Id                  int     `json:"id"`
	StudentId           string  `json:"student_id"`
	Subject             string  `json:"subject"`
	ApprovalStatus      string  `json:"approval_status"`
	RecordStatus        string  `json:"record_status"`
	StudentName         string  `json:"student_name"`
	CoachName           string  `json:"coach_name"`
	StartTime           string  `json:"start_time"`
	EndTime             string  `json:"end_time"`
	LearnrecordNumber   string  `json:"learn_record_number"`
	LastingMinute       string  `json:"lasting_minute"`
	TrainingCarType     string  `json:"training_car_type"`
	CoachLoginId        int64   `json:"coach_login_id"`
	CurHours            int     `json:"cur_hours"`
	CurMileage          float32 `json:"cur_mileage"`
	SubjectTotalHours   int64   `json:"subject_total_hours"`
	SubjectTotalMileage float64 `json:"subject_total_mileage"`
	RenKeTime           int64   `json:"ren_ke_time"`
	Five                int64   `json:"five"`
	Zero                int64   `json:"zero"`
	ZeroFive            int64   `json:"zero_five"`
}

type TaskRecord struct {
	LastingMinute int     `json:"lasting_minute"`
	Mileage       float64 `json:"mileage"`
}

type CoachRecordList struct {
	Name          string  `json:"name"`
	Phone         string  `json:"phone"`
	PlateNumber   string  `json:"plate_number"`
	Subject       string  `json:"subject"`
	StartTime     string  `json:"start_time"`
	EndTime       string  `json:"end_time"`
	LastingMinute int     `json:"lasting_minute"`
	Mileage       float32 `json:"mileage"`
	RecordStatus  string  `json:"record_status"`
}

func (l *LearnRecord) Survey(id string) (list RecordSurvey, err error) {
	_, err = engine.Table("dts_learn_record").Alias("ld").
		Select("ld.id,ld.subject,ld.end_time,ld.learnrecord_number,ld.lasting_minute,ld.start_time,ur.name as student_name,urs.name as coach_name,st.training_car_type,st.id as student_id,ld.approval_status,ld.coachloginid,ld.record_status").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").Join("LEFT", []string{"dts_user", "ur"}, "st.user_id = ur.id").
		Join("LEFT", []string{"dts_coach", "ch"}, "ch.id = ld.coach_id").Join("LEFT", []string{"dts_user", "urs"}, "urs.id = ch.user_id").
		Where("ld.id = ?", id).
		Get(&list)
	return list, err
}

func (l *LearnRecord) GetRecordList(filter builder.Cond, pageSize, offset int) (count int64, list []UnRecordList, err error) {
	err = engine.Table("dts_learn_record").Alias("ld").
		Select("ld.id,sl.name_short,ur.name as coach_name,c.plate_number as car_number,u.phone,u.name,st.training_car_type,st.operation_status,u.id_number,ld.course,ld.lasting_minute,ld.mileage,ld.`subject`,ld.start_time,ld.end_time,ld.reason, c.plate_number,ld.approval_status,ld.record_status").
		Join("left", []string{"dts_school", "sl"}, "sl.id = ld.school_id").
		Join("left", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("left", []string{"dts_user", "u"}, "st.user_id = u.id").
		Join("left", []string{"dts_coach", "ch"}, "ch.id = ld.coach_id").
		Join("left", []string{"dts_user", "ur"}, "ch.user_id = ur.id").
		Join("left", []string{"dts_car", "c"}, "c.id = ld.car_id").
		And(filter).
		Desc("ld.id").Limit(pageSize, offset).Find(&list)
	count, _ = engine.Table("dts_learn_record").Alias("ld").
		Join("left", []string{"dts_school", "sl"}, "sl.id = ld.school_id").
		Join("left", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("left", []string{"dts_user", "u"}, "st.user_id = u.id").
		And(filter).Count()
	return
}

func (l *LearnRecord) GetUnRecordListTest(filter builder.Cond) (list []UnRecordList, err error) {
	err = engine.Table("dts_learn_record").Alias("ld").
		Select("ld.id,sl.name_short,ur.name as coach_name,c.plate_number as car_number,u.phone,u.name,st.training_car_type,st.operation_status,u.id_number,ld.course,ld.lasting_minute,ld.mileage,ld.`subject`,ld.start_time,ld.end_time,ld.reason, c.plate_number,ld.approval_status,ld.record_status").
		Join("left", []string{"dts_school", "sl"}, "sl.id = ld.school_id").
		Join("left", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("left", []string{"dts_user", "u"}, "st.user_id = u.id").
		Join("left", []string{"dts_coach", "ch"}, "ch.id = ld.coach_id").
		Join("left", []string{"dts_user", "ur"}, "ch.user_id = ur.id").
		Join("left", []string{"dts_car", "c"}, "c.id = ld.car_id").
		Where("sl.province = ?", "510000").
		And(filter).
		Desc("ld.id").Find(&list)
	//log.Println(err)
	return
}

func (l *LearnRecord) GetSumMileageAndLastingMinute(filter builder.Cond) (result bool, list LearnRecord, err error) {
	result, err = engine.Table("dts_learn_record").Alias("ld").
		Select("SUM(mileage) as mileage,SUM(lasting_minute) as lasting_minute").
		And(filter).
		Get(&list)
	return result, list, err
}

type StudentPortrait struct {
	ImageUrl string
}

func (l *LearnRecord) GetPortrait(id string) (list StudentPortrait, err error) {
	_, err = engine.Table("dts_learn_record").Alias("ld").
		Select("pt.image_url").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("RIGHT", []string{"dts_portrait", "pt"}, "pt.id = st.portrait_id").
		Where("ld.id = ?", id).
		Get(&list)
	return list, err
}

func (l *LearnRecord) GetStudentAllRecord(studentId int, subject string) (list []LearnRecord, err error) {
	err = engine.Table("dts_learn_record").
		//Select("sum(lasting_minute) as lasting_minute, sum(mileage) as mileage").
		Where("student_id = ? and subject = ? and record_status = ? ", studentId, subject, "1").
		Find(&list)
	return
}

func (l *LearnRecord) GetStudentNeedReport(studentId int, subject string) (list TaskRecord, err error) {
	_, err = engine.Table("dts_learn_record").
		Select("sum(lasting_minute) as lasting_minute, sum(mileage) as mileage").
		Where("student_id = ? and subject = ? and isreport = ?  and record_status = ? ", studentId, subject, "0", "1").
		Get(&list)
	return
}

func (l *LearnRecord) GetRecordById(id string) (has bool, list LearnRecord, err error) {
	has, err = engine.Table("dts_learn_record").
		Where("id = ?", id).
		Get(&list)
	return has, list, err
}

func (l *LearnRecord) Edit(fields ...string) bool {
	var (
		err error
	)
	_, err = engine.Table("dts_learn_record").Id(l.Id).Cols(fields...).Update(l)
	if err != nil {
		log.Println(err)
		return false
	}
	return true
}

func (l *LearnRecord) GetCoachRecordList(coachId string, pageSize, offset int) (list []CoachRecordList, count int64, err error) {
	err = engine.Table("dts_learn_record").Alias("ld").
		Select("u.name,u.phone,ld.subject,ld.start_time,ld.end_time,ld.lasting_minute,ld.mileage,ld.record_status").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_user", "u"}, "u.id = st.user_id").
		Where("ld.coach_id = ?", coachId).Limit(pageSize, offset).Desc("ld.id").
		Find(&list)
	count, err = engine.Table("dts_learn_record").Alias("ld").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_user", "u"}, "u.id = st.user_id").
		Where("ld.coach_id = ?", coachId).Count()
	for k, v := range list {
		list[k].Mileage = cast.ToFloat32(utils.Decimal(cast.ToFloat64(v.Mileage/10), "2"))
	}
	return list, count, err
}

func (l *LearnRecord) GetCarRecordList(carId string, pageSize, offset int) (list []CoachRecordList, count int64, err error) {
	err = engine.Table("dts_learn_record").Alias("ld").
		Select("u.name,u.phone,ld.subject,ld.start_time,ld.end_time,ld.lasting_minute,ld.mileage,ld.record_status").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_user", "u"}, "u.id = st.user_id").
		Where("ld.car_id = ?", carId).Limit(pageSize, offset).Desc("ld.id").
		Find(&list)
	count, err = engine.Table("dts_learn_record").Alias("ld").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_user", "u"}, "u.id = st.user_id").
		Where("ld.car_id = ?", carId).Count()
	for k, v := range list {
		list[k].Mileage = cast.ToFloat32(utils.Decimal(cast.ToFloat64(v.Mileage/10), "2"))
	}
	return list, count, err
}

func (l *LearnRecord) GetTerminalCarRecordList(terminalId string) (list []CoachRecordList, count int64, err error) {
	err = engine.Table("dts_learn_record").Alias("ld").
		Select("u.name,u.phone,ld.subject,ld.start_time,ld.end_time,c.plate_number,ld.lasting_minute,ld.mileage,ld.record_status").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_car", "c"}, "ld.car_id = c.id").
		Join("LEFT", []string{"dts_user", "u"}, "u.id = st.user_id").
		Where("ld.terminal_id = ? ", terminalId).Limit(15).Desc("ld.id").
		Find(&list)
	count, err = engine.Table("dts_learn_record").Alias("ld").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_user", "u"}, "u.id = st.user_id").
		Where("ld.terminal_id = ? ", terminalId).Count()
	return
}

func (l *LearnRecord) GetTerminalUnRecordList(terminalId string) (list []CoachRecordList, count int64, err error) {
	err = engine.Table("dts_learn_record").Alias("ld").
		Select("u.name,u.phone,ld.subject,ld.start_time,ld.end_time,ld.lasting_minute,ld.mileage,ld.record_status").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_user", "u"}, "u.id = st.user_id").
		Where("ld.terminal_id = ? and ld.record_status != ?", terminalId, "1").Limit(15).Desc("ld.id").
		Find(&list)
	count, err = engine.Table("dts_learn_record").Alias("ld").
		Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_user", "u"}, "u.id = st.user_id").
		Where("ld.terminal_id = ? and ld.record_status != ?", terminalId, "1").Count()
	return
}

func (l *LearnRecord) TodoRecord(id string) bool {
	_, err := engine.Exec("update dts_learn_record set record_status = ? where terminal_id = ?", "1", id)
	return err == nil
}

func (l *LearnRecord) CheckRecordExsit(id int64) (has bool, list LearnRecord, err error) {
	has, err = engine.Table("dts_learn_record").
		Where("student_id = ?  and record_status= ?", id, "1").
		And("course like ?", "%"+"999"+"%").
		Get(&list)
	return
}

func (l *LearnRecord) GetLastRecordTime(student_id, school_id int64) (has bool, list LearnRecord, err error) {
	has, err = engine.Table("dts_learn_record").
		Where("school_id = ? and student_id = ?", school_id, student_id).
		Desc("id").
		Get(&list)
	return
}

// StartUploadSimulatorRecord start upload simulator record
func StartUploadSimulatorRecord(data map[string]interface{}, sn, subject, course, start, end, learnType string) (id int, err error) {
	startTime, err := time.ParseInLocation("20060102150405", start, time.Local)
	if err != nil {
		return 0, err
	}
	endTime, err := time.ParseInLocation("20060102150405", end, time.Local)
	if err != nil {
		return 0, err
	}
	coachs, err := GetTheoryCoachBySchoolID(cast.ToInt(data["school_id"]), cast.ToString(data["training_car_type"]), learnType)

	if err != nil {
		return 0, err
	}
	if coachs.Id <= 0 {
		return 0, errors.New("无合适的理论教练")
	}
	resp, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) {
		record := &LearnRecord{
			SchoolId:   cast.ToInt(data["school_id"]),
			StudentId:  cast.ToInt(data["student_id"]),
			CoachId:    coachs.Id,
			CarId:      99,
			TerminalId: 99,
			//Type:              data.TrainType,
			Subject:           subject,
			StartTime:         startTime,
			EndTime:           endTime,
			LastingMinute:     int(endTime.Sub(startTime).Minutes()),
			ApprovalStatus:    "0",
			RecordStatus:      "0",
			Mileage:           0,
			MaxVelocity:       0,
			Reason:            "",
			LearnrecordNumber: cast.ToString(data["class"]),
			Coachloginid:      0,
			Course:            course,
			Sn:                sn,
			Lastsn:            0,
			Mongoid:           "",
			Ispost:            "0",
			Isreport:          "0",
			ReportNum:         "",
			Ischeck:           0,
			RecordTime:        time.Now(),
			Iskaohe:           "0",
			Iscongye:          "0",
		}
		record.Type = "3"
		if num, err := session.Table("dts_learn_record").Insert(record); err != nil {
			fmt.Println(err.Error(), "insert record")
			return num, err
		}
		return record.Id, nil
	})
	//fmt.Println(resp,"resp")
	//id, err = strconv.Atoi(fmt.Sprintf("%v", resp))
	return cast.ToInt(resp), err
}

// StartUploadSimulatorFile start upload simulator file
func StartUploadSimulatorFile(id, class int, data map[string]string) (interface{}, error) {
	postTime, err := time.ParseInLocation("20060102150405", data["post_time"], time.Local)
	if err != nil {
		return nil, err
	}
	resp, err := engine.Transaction(func(session *xorm.Session) (interface{}, error) {
		gnss := &Gnss{
			LearnStatusId:     0,
			TerminalId:        99,
			Alarmflag:         0,
			Latitude:          0,
			Longitude:         0,
			Velocitycar:       0,
			Velocitysatellite: 0,
			Oritentation:      0,
			AddTime:           time.Now(),
			Status:            32767,
			Gnssmileage:       0,
			Oil:               0,
			Heightsea:         0,
			Enginespeed:       0,
			Maxspeed:          0,
			Mileage:           0,
			LearnrecordNumber: "",
			Subject:           "",
			Type:              "0",
			ApprovalStatus:    "1",
			RecordStatus:      "1",
			Checkfence:        "1",
			Datetime:          postTime,
		}
		if num, err := session.Table("dts_gnss").Insert(gnss); err != nil {
			return num, err
		}
		recordFile := &File{
			LearnRecordId:   id,
			FileType:        "1",
			FileUrl:         data["photo"],
			AddTime:         postTime,
			InstitutionCode: "",
			Status:          "0",
			FileNumber:      fmt.Sprintf("%d", postTime.Unix()),
			PhotoType:       data["photo_type"],
			Yuzhi:           100,
			GnssId:          int(gnss.Id),
		}
		if class >= 2147483647 {
			recordFile.Classid = cast.ToInt(time.Now().Unix())
		} else {
			recordFile.Classid = class
		}
		if num, err := session.Table("dts_file").Insert(recordFile); err != nil {
			return num, err
		}
		return nil, nil
	})
	return resp, err
}

type RecordUser struct {
	Id              int64
	CoachId         int64
	Student_name    string
	Coach_name      string
	Plate_number    string
	Start_time      string
	End_time        string
	Type            string
	Reason          string
	Subject         string
	Lasting_minute  int64
	Mileage         float32
	Course          string
	Record_status   string
	Approval_status string
	Temp            string
	Isreport        string
	Iscongye        string
	Iskaohe         string
	CheckStatus     string
	Title           string
	Sign            string
}

func (l *LearnRecord) GetUserLearnRecord(filter builder.Cond) (err error, count int64) {

	count, _ = engine.Table("dts_learn_record").Alias("ld").
		Join("LEFT", []string{"dts_car", "cr"}, "cr.id = ld.car_id").Join("LEFT", []string{"dts_coach", "ch"}, "ch.id = ld.coach_id").
		Join("LEFT", []string{"dts_terminal", "tl"}, "tl.id = ld.terminal_id").Join("LEFT", []string{"dts_student", "st"}, "st.id = ld.student_id").
		Join("LEFT", []string{"dts_user", "ur"}, "ur.id = ch.user_id").Join("LEFT", []string{"dts_user", "urs"}, "urs.id = st.user_id").
		And(filter).
		Count()
	log.Println(err)
	return err, count
}

// GetStudentAllLearnRecord 获取学员总学时
func (l *LearnRecord) GetStudentAllLearnRecord(student int) (list []*SubjectLearn, err error) {
	if err := engine.Table("dts_learn_record").
		Select("id,subject,type,lasting_minute,mileage,start_time,sn,isreport,iscongye,iskaohe,course").
		Where("student_id=? and  record_status=?", student, "1").Find(&list); err != nil {
		return list, err
	}
	return list, nil
}

// GetSubjectLearnRecord 获取制定科目的学时
func (l *LearnRecord) GetSubjectLearnRecord(student_id int, subject string) (list []*SubjectLearn, err error) {
	session := engine.Table("dts_learn_record").Select("id,subject,type,lasting_minute,mileage,start_time,sn,isreport,iscongye,iskaohe")
	if subject == "3" {
		if err = session.Where("student_id=? and subject in (?,?) and record_status=?", student_id, "2", "3", "1").Find(&list); err != nil {
			return nil, err
		}
	} else {
		if err = session.Where("student_id=? and subject=? and record_status=?", student_id, subject, "1").Find(&list); err != nil {
			return nil, err
		}
	}
	return list, nil
}
